﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Timers;
using WPFCommon.FileManipulation;
using WPFCommon.Interface;

namespace WPFCommon.Logger
{
    /// <summary>
    /// Provide thread safe logging services to text file in disk
    /// </summary>
    public sealed class FileLogger : IFlushAll
    {
        #region private fields

        private ConcurrentQueue<string> _messageQueue = new ConcurrentQueue<string>();
        private TimeSpan _fileLife;
        private string _logFile;
        private double _logFrequency;
        private bool _loggingStarted;

        #endregion

        #region prop

        #endregion

        #region ctor

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileLife">The time span to overwrite the log file</param>
        /// <param name="logFile">log file path</param>
        /// <param name="logFrequency">Time span to check if logging needs to be done in milliseconds</param>
        public FileLogger(TimeSpan fileLife, string logFile, double logFrequency)
        {
            _fileLife = fileLife;
            _logFile = logFile;
            _logFrequency = logFrequency;
        }

        #endregion

        #region api

        public void EnqueueMessage(string message)
        {
            var now = DateTime.Now.ToString("G");
            var line = $"{now} : {message}{Environment.NewLine}";
            _messageQueue.Enqueue(line);
        }

        public void StartLogging()
        {
            if (_loggingStarted) return;
            _loggingStarted = true;

            var logClock = new System.Timers.Timer() {Enabled = true, Interval = _logFrequency};
            logClock.Elapsed += LogAvailableMessages;
        }

        private void LogAvailableMessages(object sender, ElapsedEventArgs e)
        {
            // Create file
            FileHelper.CreateEmptyFileAndContainingFolder(_logFile);

            // If file is outdated, remove
            if (FileHelper.RemoveOutdatedFile(_logFile, _fileLife)) return;

            var lines = new List<string>();
            while (_messageQueue.TryDequeue(out var message))
            {
                lines.Add(message);
            }

            if (!lines.Any()) return;

            var content = string.Join(Environment.NewLine, lines);
            File.AppendAllText(_logFile, content);
        }

        public void FlushAll()
        {
            LogAvailableMessages(null, null);
        }

        #endregion
    }
}